package com.jk.myimkit.imkit.plugin.location;

import android.content.Context;
import android.text.TextUtils;

import com.amap.api.maps2d.CoordinateConverter;
import com.amap.api.maps2d.model.LatLng;
import com.amap.api.netlocation.AMapNetworkLocationClient;

import java.util.List;

import io.rong.common.RLog;
import io.rong.imlib.RongIMClient;
import io.rong.imlib.location.RealTimeLocationConstant;
import io.rong.imlib.location.RealTimeLocationType;
import io.rong.imlib.model.Conversation;

public class LocationManager {
    private static final String TAG = "LocationManager";
    private Context mContext;
    private Conversation.ConversationType mConversationType;
    private String mTargetId;
    private IRealTimeLocationStateListener mParticipantChangedListener;
    private IMyLocationChangedListener mMyLocationChangedListener;
    private ILocationChangedListener mLocationChangedListener;
    private AMapLocationParser mLocationParser;
    private AMapNetworkLocationClient mLocationClient;
    private LatLng mLatLng;
    private AMapLocationInfo mMyLastLatLng;
    private LocationManager.LoopThread mLoopThread;
    private IUserInfoProvider mUserInfoProvider;

    private LocationManager() {
    }

    public static LocationManager getInstance() {
        return LocationManager.SingletonHolder.INSTANCE;
    }

    public void getUserInfo(String userId, IUserInfoProvider.UserInfoCallback userInfoCallback) {
        if (this.mUserInfoProvider != null) {
            this.mUserInfoProvider.getUserInfo(userId, userInfoCallback);
        }

    }

    public void bindConversation(Context context, Conversation.ConversationType conversationType, String targetId) {
        RLog.d("LocationManager", "bindConversation context = " + context);
        this.mContext = context.getApplicationContext();
        this.mConversationType = conversationType;
        this.mTargetId = targetId;
        this.mLocationParser = new AMapLocationParser();
        RongIMClient.getInstance().addRealTimeLocationListener(this.mConversationType, this.mTargetId, new RongIMClient.RealTimeLocationListener() {
            public void onStatusChange(RealTimeLocationConstant.RealTimeLocationStatus status) {
                RLog.d("LocationManager", "onStatusChange status = " + status.getMessage());
                LocationManager.this.sendOnParticipantChanged();
            }

            public void onReceiveLocationWithType(double latitude, double longitude, RealTimeLocationType type, String userId) {
                RLog.d("LocationManager", "onReceiveLocationWithType userId = " + userId + "; latitude = " + latitude + "; longitude = " + longitude + ",type = " + type);
                if (type != RealTimeLocationType.WGS84 || latitude == 0.0D && longitude == 0.0D) {
                    if (userId.equals(RongIMClient.getInstance().getCurrentUserId())) {
                        LocationManager.this.mLatLng = new LatLng(latitude, longitude);
                    }

                    LocationManager.this.sendOnLocationChanged(latitude, longitude, userId);
                } else {
                    LatLng sourceLatLng = new LatLng(latitude, longitude);
                    CoordinateConverter converter = new CoordinateConverter();
                    converter.from(CoordinateConverter.CoordType.GPS);
                    converter.coord(sourceLatLng);
                    LatLng desLatLng = converter.convert();
                    if (userId.equals(RongIMClient.getInstance().getCurrentUserId())) {
                        LocationManager.this.mLatLng = new LatLng(desLatLng.latitude, desLatLng.longitude);
                    }

                    LocationManager.this.sendOnLocationChanged(desLatLng.latitude, desLatLng.longitude, userId);
                }

            }

            public void onReceiveLocation(double latitude, double longitude, String userId) {
                RLog.d("LocationManager", "onReceiveLocation userId = " + userId + "; latitude = " + latitude + "; longitude = " + longitude);
                if (userId.equals(RongIMClient.getInstance().getCurrentUserId())) {
                    LocationManager.this.mLatLng = new LatLng(latitude, longitude);
                }

                LocationManager.this.sendOnLocationChanged(latitude, longitude, userId);
            }

            public void onParticipantsJoin(String userId) {
                RLog.d("LocationManager", "onParticipantsJoin userId = " + userId);
                LocationManager.this.sendOnParticipantChanged();
                LocationManager.this.sendOnParticipantJoinSharing(userId);
            }

            public void onParticipantsQuit(String userId) {
                RLog.d("LocationManager", "onParticipantsQuit userId = " + userId);
                LocationManager.this.sendOnParticipantChanged();
                LocationManager.this.sendOnParticipantQuitSharing(userId);
            }

            public void onError(RealTimeLocationConstant.RealTimeLocationErrorCode errorCode) {
                RLog.d("LocationManager", "RealTimeLocationErrorCode errorCode = " + errorCode);
                LocationManager.this.stopMyLocationInLoop();
                LocationManager.this.sendOnRealTimeLocationError(errorCode);
            }
        });
    }

    public void unBindConversation() {
        RongIMClient.getInstance().removeRealTimeLocationObserver(this.mConversationType, this.mTargetId);
    }

    public void setUserInfoProvider(IUserInfoProvider userInfoProvider) {
        this.mUserInfoProvider = userInfoProvider;
    }

    public void setParticipantChangedListener(IRealTimeLocationStateListener listener) {
        this.mParticipantChangedListener = listener;
        if (this.mParticipantChangedListener != null) {
            this.mParticipantChangedListener.onParticipantChanged(RongIMClient.getInstance().getRealTimeLocationParticipants(this.mConversationType, this.mTargetId));
        }

    }

    public void setMyLocationChangedListener(IMyLocationChangedListener listener) {
        this.mMyLocationChangedListener = listener;
        if (this.mMyLocationChangedListener != null) {
            this.updateMyLocation();
            if (this.mMyLastLatLng != null) {
                listener.onMyLocationChanged(this.mMyLastLatLng);
            }
        }

    }

    public void setLocationChangedListener(ILocationChangedListener listener) {
        this.mLocationChangedListener = listener;
        if (this.mLocationChangedListener != null && this.mLatLng != null) {
            this.mLocationChangedListener.onLocationChanged(this.mLatLng.latitude, this.mLatLng.longitude, RongIMClient.getInstance().getCurrentUserId());
        }

    }

    public int joinLocationSharing() {
        RongIMClient.ConnectionStatusListener.ConnectionStatus state = RongIMClient.getInstance().getCurrentConnectionStatus();
        if (state != RongIMClient.ConnectionStatusListener.ConnectionStatus.CONNECTED) {
            return 1;
        } else {
            RealTimeLocationConstant.RealTimeLocationStatus status = RongIMClient.getInstance().getRealTimeLocationCurrentState(this.mConversationType, this.mTargetId);
            switch(status) {
                case RC_REAL_TIME_LOCATION_STATUS_IDLE:
                    RongIMClient.getInstance().startRealTimeLocation(this.mConversationType, this.mTargetId);
                    break;
                case RC_REAL_TIME_LOCATION_STATUS_INCOMING:
                    int errorCode = RongIMClient.getInstance().joinRealTimeLocation(this.mConversationType, this.mTargetId).getValue();
                    if (errorCode == RealTimeLocationConstant.RealTimeLocationErrorCode.RC_REAL_TIME_LOCATION_EXCEED_MAX_PARTICIPANT.getValue()) {
                        return 2;
                    }
            }

            return 0;
        }
    }

    public void quitLocationSharing() {
        RLog.d("LocationManager", "quitLocationSharing");
        RealTimeLocationConstant.RealTimeLocationStatus status = RongIMClient.getInstance().getRealTimeLocationCurrentState(this.mConversationType, this.mTargetId);
        if (status == RealTimeLocationConstant.RealTimeLocationStatus.RC_REAL_TIME_LOCATION_STATUS_CONNECTED || status == RealTimeLocationConstant.RealTimeLocationStatus.RC_REAL_TIME_LOCATION_STATUS_OUTGOING) {
            RongIMClient.getInstance().quitRealTimeLocation(this.mConversationType, this.mTargetId);
            this.stopMyLocationInLoop();
            this.mLatLng = null;
        }

    }

    public void updateMyLocation() {
        LocationManager.MyLocationThread thread = new LocationManager.MyLocationThread();
        thread.start();
    }

    public void updateMyLocationInLoop(int sec) {
        if (this.mLoopThread != null) {
            this.mLoopThread.stopLooping();
        }

        this.mLoopThread = new LocationManager.LoopThread(sec);
        this.mLoopThread.start();
    }

    public void stopMyLocationInLoop() {
        if (this.mLoopThread != null) {
            this.mLoopThread.stopLooping();
            this.mLoopThread = null;
        }

    }

    public boolean isSharing() {
        RealTimeLocationConstant.RealTimeLocationStatus status = RongIMClient.getInstance().getRealTimeLocationCurrentState(this.mConversationType, this.mTargetId);
        return status == RealTimeLocationConstant.RealTimeLocationStatus.RC_REAL_TIME_LOCATION_STATUS_CONNECTED || status == RealTimeLocationConstant.RealTimeLocationStatus.RC_REAL_TIME_LOCATION_STATUS_OUTGOING;
    }

    private void sendOnParticipantChanged() {
        if (this.mContext != null && this.mParticipantChangedListener != null) {
            List<String> userIdList = RongIMClient.getInstance().getRealTimeLocationParticipants(this.mConversationType, this.mTargetId);
            this.mParticipantChangedListener.onParticipantChanged(userIdList);
        }

    }

    private void sendOnMyLocationChanged(AMapLocationInfo locInfo) {
        if (this.mContext != null && this.mMyLocationChangedListener != null && locInfo != null) {
            this.mMyLocationChangedListener.onMyLocationChanged(locInfo);
        }

    }

    private void sendOnRealTimeLocationError(RealTimeLocationConstant.RealTimeLocationErrorCode code) {
        if (this.mContext != null && this.mLocationChangedListener != null) {
            this.mLocationChangedListener.onError(code);
        }

        if (this.mParticipantChangedListener != null) {
            this.mParticipantChangedListener.onErrorException();
        }

    }

    private void sendOnLocationChanged(double latitude, double longitude, String userId) {
        if (this.mContext != null && this.mLocationChangedListener != null) {
            this.mLocationChangedListener.onLocationChanged(latitude, longitude, userId);
        }

    }

    private void sendOnParticipantJoinSharing(String userId) {
        if (this.mContext != null && this.mLocationChangedListener != null) {
            this.mLocationChangedListener.onParticipantJoinSharing(userId);
        }

    }

    private void sendOnParticipantQuitSharing(String userId) {
        if (this.mContext != null && this.mLocationChangedListener != null) {
            this.mLocationChangedListener.onParticipantQuitSharing(userId);
        }

    }

    private class MyLocationThread extends Thread {
        private MyLocationThread() {
        }

        public void run() {
            if (LocationManager.this.mLocationClient == null) {
                LocationManager.this.mLocationClient = new AMapNetworkLocationClient(LocationManager.this.mContext);
                LocationManager.this.mLocationClient.setApiKey("8bc77f14ab831d62baaf2ed17fb798a4");
            }

            String locStr = LocationManager.this.mLocationClient.getNetworkLocation();
            RLog.d("LocationManager", "MyLocationThread location: " + locStr);
            AMapLocationInfo locInfo = LocationManager.this.mLocationParser.parserApsJsonResp(locStr);
            LocationManager.this.sendOnMyLocationChanged(locInfo);
            LocationManager.this.mMyLastLatLng = locInfo;
        }
    }

    private class LoopThread extends Thread {
        private boolean mLooping;
        private int mMilSec;

        public LoopThread(int sec) {
            this.mMilSec = sec * 1000;
        }

        public void stopLooping() {
            this.mLooping = false;
        }

        public void run() {
            this.mLooping = true;

            while(this.mLooping) {
                if (LocationManager.this.mLocationClient == null) {
                    LocationManager.this.mLocationClient = new AMapNetworkLocationClient(LocationManager.this.mContext);
                    LocationManager.this.mLocationClient.setApiKey("8bc77f14ab831d62baaf2ed17fb798a4");
                }

                String locStr = LocationManager.this.mLocationClient.getNetworkLocation();
                RLog.d("LocationManager", "LoopThread location: " + locStr);
                if (!TextUtils.isEmpty(locStr)) {
                    AMapLocationInfo locInfo = LocationManager.this.mLocationParser.parserApsJsonResp(locStr);
                    RealTimeLocationType realTimeLocationType;
                    if (locInfo.getCoord() == 1) {
                        realTimeLocationType = RealTimeLocationType.GCJ02;
                    } else {
                        realTimeLocationType = RealTimeLocationType.WGS84;
                    }

                    RongIMClient.getInstance().updateRealTimeLocationStatus(LocationManager.this.mConversationType, LocationManager.this.mTargetId, locInfo.getLat(), locInfo.getLng(), realTimeLocationType);
                    LocationManager.this.mMyLastLatLng = locInfo;
                }

                try {
                    sleep((long)this.mMilSec);
                } catch (InterruptedException var4) {
                    var4.printStackTrace();
                }
            }

        }
    }

    private static class SingletonHolder {
        private static final LocationManager INSTANCE = new LocationManager();

        private SingletonHolder() {
        }
    }
}
